/*-------------------------------------------------------------------------
 *
 * gistxlog.h
 *	  gist xlog 例程
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/access/gistxlog.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef GIST_XLOG_H
#define GIST_XLOG_H

#include "access/gist.h"
#include "access/xlogreader.h"
#include "lib/stringinfo.h"

#define XLOG_GIST_PAGE_UPDATE		0x00
#define XLOG_GIST_DELETE			0x10	/* 删除页面的叶索引元组 */
#define XLOG_GIST_PAGE_REUSE		0x20	/* 旧页面即将被从 FSM 重新使用 */
#define XLOG_GIST_PAGE_SPLIT		0x30
 /* #define XLOG_GIST_INSERT_COMPLETE 0x40 */	/* 不再使用 */
 /* #define XLOG_GIST_CREATE_INDEX		 0x50 */	/* 不再使用 */
#define XLOG_GIST_PAGE_DELETE		0x60
#define XLOG_GIST_ASSIGN_LSN		0x70	/* nop，分配新的 LSN */

/*
 * 备份块 0：更新的页面。
 * 备份块 1：如果此操作完成了页面拆分，通过插入
 *				 拆分页面的下链接，拆分的左半部分
 */
typedef struct gistxlogPageUpdate
{
	/* 被删除的偏移量数量 */
	uint16		ntodelete;
	uint16		ntoinsert;

	/*
	 * 在块 0 的负载中：1. 要删除的偏移量 2. 要插入的元组
	 */
} gistxlogPageUpdate;

/*
 * 备份块 0：索引元组被删除的叶子页面。
 */
typedef struct gistxlogDelete
{
	TransactionId latestRemovedXid;
	uint16		ntodelete;		/* 被删除的偏移量数量 */

	/*
	 * 在块 0 的负载中：要删除的偏移量
	 */
} gistxlogDelete;

#define SizeOfGistxlogDelete	(offsetof(gistxlogDelete, ntodelete) + sizeof(uint16))

/*
 * 备份块 0：如果此操作完成了页面拆分，通过插入
 *				 拆分页面的下链接，拆分的左半部分
 * 备份块 1 - npage：拆分页面（1 是原页面）
 */
typedef struct gistxlogPageSplit
{
	BlockNumber origrlink;		/* 拆分前页面的右链接 */
	GistNSN		orignsn;		/* 拆分前页面的 NSN */
	bool		origleaf;		/* 被拆分的页面是叶子页面吗？ */

	uint16		npage;			/* 拆分中的页面数量 */
	bool		markfollowright;	/* 设置 F_FOLLOW_RIGHT 标志 */

	/*
	 * follow: 1. gistxlogPage 和每个页面的 IndexTupleData 数组
	 */
} gistxlogPageSplit;

/*
 * 备份块 0：被删除的页面。
 * 备份块 1：父页面，包含指向被删除页面的下行链接。
 */
typedef struct gistxlogPageDelete
{
	FullTransactionId deleteXid;	/* 最后一个可以在扫描中看到页面的 Xid */
	OffsetNumber downlinkOffset;	/* 对应此页面的下行链接的偏移量 */
} gistxlogPageDelete;

#define SizeOfGistxlogPageDelete	(offsetof(gistxlogPageDelete, downlinkOffset) + sizeof(OffsetNumber))


/*
 * 这是我们需要了解热备的页面重用情况。
 */
typedef struct gistxlogPageReuse
{
	RelFileNode node;
	BlockNumber block;
	FullTransactionId latestRemovedFullXid;
} gistxlogPageReuse;

#define SizeOfGistxlogPageReuse	(offsetof(gistxlogPageReuse, latestRemovedFullXid) + sizeof(FullTransactionId))

extern void gist_redo(XLogReaderState *record);
extern void gist_desc(StringInfo buf, XLogReaderState *record);
extern const char *gist_identify(uint8 info);
extern void gist_xlog_startup(void);
extern void gist_xlog_cleanup(void);
extern void gist_mask(char *pagedata, BlockNumber blkno);

#endif
